import { BaseEntity } from '../domain/entities/BaseEntity';
import { Item } from '../domain/entities/Item';
import { Player } from '../domain/entities/Player';
import { ModernBaseService } from '../service/base/ModernBaseService';

/**
 * 背包数据访问层
 * 职责：
 * 1. 背包数据的持久化
 * 2. 背包查询和更新操作
 * 3. 数据缓存管理
 * 4. 数据验证和转换
 */
export class BagRepository extends ModernBaseService {
    private playerBagCache = new Map<string, CachedBagData>();
    private readonly CACHE_TTL = 300000; // 5分钟缓存

    /**
     * 获取玩家背包数据
     * @param playerId 玩家ID
     * @returns 背包数据
     */
    async getPlayerBag(playerId: string): Promise<PlayerBagData> {
        return this.cached(`bag_${playerId}`, async () => {
            this.validateRequiredParams({ playerId }, ['playerId']);

            const player = this.sdk.getPlayerById(playerId);
            if (!player) {
                throw new Error(`Player ${playerId} not found`);
            }

            // 从玩家组件获取背包数据
            const bagComponent = player.getComponent('背包');
            if (!bagComponent) {
                // 如果没有背包组件，创建默认背包
                return this.createDefaultBag(playerId);
            }

            // 转换为标准格式
            const bagData: PlayerBagData = {
                playerId,
                items: this.convertItemsToEntities(bagComponent.itemList || []),
                maxSize: bagComponent.maxSize || 100,
                lastUpdated: new Date()
            };

            return bagData;
        }, this.CACHE_TTL);
    }

    /**
     * 保存玩家背包数据
     * @param playerId 玩家ID
     * @param bagData 背包数据
     */
    async savePlayerBag(playerId: string, bagData: PlayerBagData): Promise<void> {
        await this.safeExecute(async () => {
            this.validateRequiredParams({ playerId, bagData }, ['playerId', 'bagData']);

            const player = this.sdk.getPlayerById(playerId);
            if (!player) {
                throw new Error(`Player ${playerId} not found`);
            }

            // 获取背包组件
            let bagComponent = player.getComponent('背包');
            if (!bagComponent) {
                bagComponent = player.addComponent('背包');
            }

            // 转换Entity为原始格式并保存
            bagComponent.itemList = this.convertEntitiesToItems(bagData.items);
            bagComponent.maxSize = bagData.maxSize;

            // 更新缓存
            this.updateCache(playerId, bagData);

            this.log(`Bag data saved for player ${playerId}, items: ${bagData.items.length}`);
        }, 'savePlayerBag');
    }

    /**
     * 添加物品到背包
     * @param playerId 玩家ID
     * @param item 物品实体
     * @returns 添加结果
     */
    async addItemToBag(playerId: string, item: Item): Promise<BagOperationResult> {
        return this.withPerformanceMonitoring(async () => {
            const bagData = await this.getPlayerBag(playerId);
            
            // 检查背包是否已满
            if (bagData.items.length >= bagData.maxSize) {
                return {
                    success: false,
                    message: '背包已满',
                    items: bagData.items,
                    addedCount: 0
                };
            }

            // 尝试堆叠
            const stackResult = this.tryStackItem(bagData.items, item);
            if (stackResult.success) {
                bagData.lastUpdated = new Date();
                await this.savePlayerBag(playerId, bagData);
                
                return {
                    success: true,
                    message: `成功添加 ${item.name} x${stackResult.addedCount}`,
                    items: bagData.items,
                    addedCount: stackResult.addedCount
                };
            }

            // 无法堆叠，添加新物品
            const newItem = item.clone();
            bagData.items.push(newItem);
            bagData.lastUpdated = new Date();
            
            await this.savePlayerBag(playerId, bagData);

            return {
                success: true,
                message: `获得 ${item.name} x${item.count}`,
                items: bagData.items,
                addedCount: item.count
            };
        }, 'addItemToBag');
    }

    /**
     * 从背包移除物品
     * @param playerId 玩家ID
     * @param itemId 物品ID
     * @param count 移除数量
     * @returns 移除结果
     */
    async removeItemFromBag(playerId: string, itemId: string, count: number): Promise<BagOperationResult> {
        return this.withPerformanceMonitoring(async () => {
            const bagData = await this.getPlayerBag(playerId);
            
            const itemIndex = bagData.items.findIndex(item => item.id === itemId);
            if (itemIndex === -1) {
                return {
                    success: false,
                    message: '物品不存在',
                    items: bagData.items,
                    removedCount: 0
                };
            }

            const item = bagData.items[itemIndex];
            if (item.count < count) {
                return {
                    success: false,
                    message: '物品数量不足',
                    items: bagData.items,
                    removedCount: 0
                };
            }

            let removedCount = 0;
            if (item.count === count) {
                // 完全移除
                bagData.items.splice(itemIndex, 1);
                removedCount = count;
            } else {
                // 减少数量
                item.count -= count;
                removedCount = count;
            }

            bagData.lastUpdated = new Date();
            await this.savePlayerBag(playerId, bagData);

            return {
                success: true,
                message: `移除 ${item.name} x${removedCount}`,
                items: bagData.items,
                removedCount
            };
        }, 'removeItemFromBag');
    }

    /**
     * 查找背包中的物品
     * @param playerId 玩家ID
     * @param itemId 物品ID
     * @param itemType 物品类型（可选）
     * @returns 物品实体
     */
    async findItemInBag(playerId: string, itemId: string, itemType?: string): Promise<Item | null> {
        const bagData = await this.getPlayerBag(playerId);
        
        return bagData.items.find(item => {
            const idMatch = item.id === itemId;
            const typeMatch = itemType ? item.type.toString() === itemType : true;
            return idMatch && typeMatch;
        }) || null;
    }

    /**
     * 整理背包
     * @param playerId 玩家ID
     * @returns 整理结果
     */
    async organizeBag(playerId: string): Promise<BagOperationResult> {
        return this.withPerformanceMonitoring(async () => {
            const bagData = await this.getPlayerBag(playerId);
            
            // 按类型和品质排序
            bagData.items.sort((a, b) => {
                if (a.type !== b.type) {
                    return a.type.localeCompare(b.type.toString());
                }
                if (a.quality !== b.quality) {
                    return b.quality - a.quality; // 品质从高到低
                }
                return a.name.localeCompare(b.name);
            });

            // 尝试合并可堆叠物品
            const mergedItems: Item[] = [];
            for (const item of bagData.items) {
                if (item.stackable) {
                    const existingItem = mergedItems.find(merged => 
                        merged.id === item.id && merged.canStackWith(item)
                    );
                    if (existingItem) {
                        existingItem.stackWith(item);
                        continue;
                    }
                }
                mergedItems.push(item);
            }

            bagData.items = mergedItems;
            bagData.lastUpdated = new Date();
            
            await this.savePlayerBag(playerId, bagData);

            return {
                success: true,
                message: '背包整理完成',
                items: bagData.items,
                organizedCount: bagData.items.length
            };
        }, 'organizeBag');
    }

    /**
     * 获取背包统计信息
     * @param playerId 玩家ID
     * @returns 统计信息
     */
    async getBagStatistics(playerId: string): Promise<BagStatistics> {
        const bagData = await this.getPlayerBag(playerId);
        
        const stats: BagStatistics = {
            totalItems: bagData.items.length,
            maxSize: bagData.maxSize,
            usagePercentage: Math.round((bagData.items.length / bagData.maxSize) * 100),
            itemsByType: {},
            itemsByQuality: {},
            totalValue: 0
        };

        bagData.items.forEach(item => {
            // 按类型统计
            const type = item.type.toString();
            stats.itemsByType[type] = (stats.itemsByType[type] || 0) + item.count;

            // 按品质统计
            const quality = item.getQualityName();
            stats.itemsByQuality[quality] = (stats.itemsByQuality[quality] || 0) + item.count;

            // 总价值
            stats.totalValue += item.value * item.count;
        });

        return stats;
    }

    /**
     * 批量操作物品
     * @param playerId 玩家ID
     * @param operations 操作列表
     * @returns 批量操作结果
     */
    async batchItemOperations(playerId: string, operations: BagOperation[]): Promise<BatchOperationResult> {
        this.log(`Starting batch bag operations: ${operations.length} operations`);
        
        const results: BagOperationResult[] = [];
        const errors: { index: number; operation: BagOperation; error: string }[] = [];

        for (let i = 0; i < operations.length; i++) {
            try {
                const operation = operations[i];
                let result: BagOperationResult;
                
                switch (operation.type) {
                    case 'add':
                        result = await this.addItemToBag(playerId, operation.item!);
                        break;
                    case 'remove':
                        result = await this.removeItemFromBag(playerId, operation.itemId!, operation.count!);
                        break;
                    case 'organize':
                        result = await this.organizeBag(playerId);
                        break;
                    default:
                        throw new Error(`Unknown operation type: ${operation.type}`);
                }
                results.push(result);
            } catch (error) {
                errors.push({
                    index: i,
                    operation: operations[i],
                    error: (error as any).message || 'Unknown error'
                });
            }
        }

        const success = errors.length === 0;
        this.log(`Batch bag operations ${success ? 'completed' : 'completed with errors'}`, 
                 success ? 'info' : 'warn');

        return { success, results, errors };
    }

    /**
     * 清理过期缓存
     */
    async cleanupCache(): Promise<void> {
        const now = Date.now();
        for (const [playerId, cached] of this.playerBagCache) {
            if (now - cached.timestamp > this.CACHE_TTL) {
                this.playerBagCache.delete(playerId);
            }
        }
        this.log(`Cache cleanup completed, remaining entries: ${this.playerBagCache.size}`);
    }

    /**
     * 尝试堆叠物品
     * @param items 物品列表
     * @param newItem 新物品
     * @returns 堆叠结果
     */
    private tryStackItem(items: Item[], newItem: Item): { success: boolean; addedCount: number } {
        if (!newItem.stackable) {
            return { success: false, addedCount: 0 };
        }

        const existingItem = items.find(item => item.canStackWith(newItem));
        if (existingItem) {
            const stackResult = existingItem.stackWith(newItem);
            return { success: stackResult.success, addedCount: stackResult.stackedAmount };
        }

        return { success: false, addedCount: 0 };
    }

    /**
     * 转换物品数组为Entity
     * @param items 原始物品数组
     * @returns Entity数组
     */
    private convertItemsToEntities(items: any[]): Item[] {
        return items.map(itemData => {
            const item = Item.create({
                id: itemData.id,
                name: itemData.name,
                description: itemData.desc || '',
                type: itemData.type,
                quality: itemData.quality,
                icon: itemData.icon || '',
                emoji: itemData.emoji || '',
                count: itemData.count || 1,
                stackable: itemData.stacking !== false,
                data: itemData.data || {}
            });
            return item;
        });
    }

    /**
     * 转换Entity为原始物品格式
     * @param items Entity数组
     * @returns 原始物品数组
     */
    private convertEntitiesToItems(items: Item[]): any[] {
        return items.map(item => ({
            uuid: item.id,
            id: item.id,
            name: item.name,
            desc: item.description,
            type: item.type,
            quality: item.quality,
            icon: item.icon,
            emoji: item.emoji,
            count: item.count,
            stacking: item.stackable,
            data: item.data
        }));
    }

    /**
     * 创建默认背包
     * @param playerId 玩家ID
     * @returns 默认背包数据
     */
    private createDefaultBag(playerId: string): PlayerBagData {
        return {
            playerId,
            items: [],
            maxSize: 100,
            lastUpdated: new Date()
        };
    }

    /**
     * 更新缓存
     * @param playerId 玩家ID
     * @param bagData 背包数据
     */
    private updateCache(playerId: string, bagData: PlayerBagData): void {
        this.playerBagCache.set(playerId, {
            data: bagData,
            timestamp: Date.now()
        });
    }
}

/**
 * 玩家背包数据接口
 */
export interface PlayerBagData {
    playerId: string;
    items: Item[];
    maxSize: number;
    lastUpdated: Date;
}

/**
 * 缓存数据接口
 */
interface CachedBagData {
    data: PlayerBagData;
    timestamp: number;
}

/**
 * 背包操作结果接口
 */
export interface BagOperationResult {
    success: boolean;
    message: string;
    items: Item[];
    addedCount?: number;
    removedCount?: number;
    organizedCount?: number;
}

/**
 * 背包统计信息接口
 */
export interface BagStatistics {
    totalItems: number;
    maxSize: number;
    usagePercentage: number;
    itemsByType: Record<string, number>;
    itemsByQuality: Record<string, number>;
    totalValue: number;
}

/**
 * 背包操作接口
 */
export interface BagOperation {
    type: 'add' | 'remove' | 'organize';
    item?: Item;
    itemId?: string;
    count?: number;
}

/**
 * 批量操作结果接口
 */
export interface BatchOperationResult {
    success: boolean;
    results: BagOperationResult[];
    errors: { index: number; operation: BagOperation; error: string }[];
}
